/*
 * WTF.cpp
 *
 *  Created on: Apr 4, 2012
 *      Author: kriwtal
 */

//============================================================================
// Name        : Logger.cpp
// Author      :
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//write to file
//priority (error, warning, dbg)
//rotate(log.txt>10 Mg-> txt1)
//time
//smp
//svn
//============================================================================
#include <stdio.h>
#include <stdlib.h>
#include <cstdio>
#include<time.h>
#include <fcntl.h>
#include<fstream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <errno.h>
#include <cstdlib>
#include <iostream>
#include<fstream>
#include<string.h>
#include <iostream>
using namespace std;
//class Log;

enum Type_of_Logging {
	warning,
	error,
	debug
};
struct data {
	time_t Time;
	Type_of_Logging What_happened;
	string Who;
	string msg;

};

class Ring_Buffer {
	friend struct data;
	//friend class Log;
private:

	data* _data;
	int size;
	int readptr;
	int writeptr;

	int writeAvail;
public:

	Ring_Buffer(int NumberOfRecords) {
		_data = new data[NumberOfRecords];
		memset(_data, 0, NumberOfRecords);
		size = NumberOfRecords;
		readptr = 0;
		writeptr = 0;
		writeAvail = NumberOfRecords;
	}
	~Ring_Buffer() {
		delete[] _data;
	}
	//
	int Read(data *dataPtr, int numBytes) {
		//if no data or no data-cant't read
		if (dataPtr == 0 || numBytes <= 0 || writeAvail == size) {
			return 0;
		}
		int readBytesAvail = size - writeAvail;
		//cap our read ata the number of bytes avail. to be read
		if (numBytes > readBytesAvail) {
			numBytes = readBytesAvail;
		}
		//keep track of how many bytes we've read and our position in the outgoing buff
		if (numBytes > size - readptr) {
			int len = size - readptr;
			memcpy(dataPtr, _data + readptr, len);
			memcpy(dataPtr + len, _data, numBytes - len);
		} else {

			memcpy(dataPtr, _data + readptr, numBytes);
		}
		readptr = (readptr + numBytes) % size;
		writeAvail += numBytes;
		return numBytes;

	}
	int Write(data *dataPtr, int numBytes) {
		// If there's nothing to write or no room available, we can't write anything.
		if (dataPtr == 0 || numBytes <= 0 || writeAvail == 0) {
			return 0;
		}

		// Cap our write at the number of bytes available to be written.
		if (numBytes > writeAvail) {
			numBytes = writeAvail;
		}

		// Simultaneously keep track of how many bytes we've written and our position in the incoming buffer
		if (numBytes > size - writeptr) {
			int len = size - writeptr;
			memcpy(_data + writeptr, dataPtr, len);
			memcpy(_data, dataPtr + len, numBytes - len);
		} else {
			memcpy(_data + writeptr, dataPtr, numBytes);
		}

		writeptr = (writeptr + numBytes) % size;
		writeAvail -= numBytes;

		return numBytes;

	}
	//Set all data to 0 and set buffer flag as empty
	bool Empty(void) {
		memset(_data, 0, size);
		readptr = 0;
		writeptr = 0;
		writeAvail = size;
		return true;
	}
	int Get_Size(void) {
		return size;
	}
	int WriteAvail(void) {
		return writeAvail;
	}
	int GetReadAvail(void) {
		return size - writeAvail;
	}

};

class Log {
	friend struct data;
public:
	Ring_Buffer *Buffer;
	FILE *fd;
	int BufferSize;
	int Count_of_Log_Files;
	//time_t Time;
	data *ptr;
	//data Data;

	Log(int Size = 10) {
		Count_of_Log_Files = 0;
		BufferSize = Size;
		Buffer = new Ring_Buffer(Size);
		fd = fopen("Log.txt", "a+");
		ptr = NULL;
	}

	~Log() {
	}
	void write_to_file() {

		data Record;
		Buffer->Read(&Record, sizeof(data));
		if (ftell(fd) < 10000000) {
			fprintf(fd, "%s = %d = %s = %s\n", ctime(&Record.Time),
					Record.What_happened, Record.Who.c_str(),
					Record.msg.c_str());
		} else {
			fclose(fd);
			string name = "Log.txt";
			char * num = new char[5];
			sprintf(num, "%d", Count_of_Log_Files);
			name.insert(name.find_last_of('.') - 1, num);
			while ((rename("Log.txt", name.c_str()) != 0)) {
				Count_of_Log_Files++;
			}

			fd = fopen("Log.txt", "a+");

		}

	}
	void write_log_data(string Name, string Msg, Type_of_Logging What_happened_Type) {
		data Record;
		Record.Time = time(NULL);
		Record.What_happened = What_happened_Type;
		Record.Who = Name;
		Record.msg = Msg;
		while (Buffer->Write(&Record, sizeof(data)) == sizeof(data)) {
			write_to_file();
		}

	}

};

int main() {

	Log log;
	log.write_log_data("main","ok",debug);
	log.write_to_file();
	cout << "ololo" << endl; // prints !!!Hello World!!!
	return 0;
}

